using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

//与unity的场景管理器命名冲突，因此改为MySceneManager
public class MySceneManager : MonoBehaviour
{
    //场景中挂载逻辑的GameObject的名称
    private string m_LogicName = "[SceneLogic]";

    private void Awake()
    {
        //SceneManager类中场景切换时候触发的事件，为他注册一个回调，执行脚本中切换时对应的逻辑。
        //当使用SetActiveScene（）函数/或在unity编辑器中活动场景变化的时候会触发该事件。
        SceneManager.activeSceneChanged += OnActiveSceneChanged;
    }
    /// <summary>
    /// 场景切换的回调，调用场景逻辑中lua的激活与非激活函数
    /// </summary>
    /// <param name="s1"></param>
    /// <param name="s2"></param>
    private void OnActiveSceneChanged(Scene s1, Scene s2)
    {
        if (s1.isLoaded && s2.isLoaded)
        {
            SceneLogic sceneLogic1 = GetSceneLogic(s1);
            SceneLogic sceneLogic2 = GetSceneLogic(s2);

            sceneLogic1?.OnInActive();
            sceneLogic2?.OnActive();
        }
    }
    /// <summary>
    /// 激活场景
    /// </summary>
    /// <param name="sceneName"></param>
    public void SetActive(string sceneName)
    {
        Scene scene = SceneManager.GetSceneByName(sceneName);
        SceneManager.SetActiveScene(scene);
    }



    /// <summary>
    /// 两种加载场景的方式????????????
    /// </summary>
    /// <param name="sceneName"></param>
    /// <param name="luaName"></param>
    public void LoadScene(string sceneName, string luaName)
    {
        Manager.Resource.LoadScene(sceneName, (Object obj) =>
        {
            StartCoroutine(StartLoadScene(sceneName, luaName, LoadSceneMode.Additive));
        });
    }

    public void LoadScene2(string sceneName, string luaName)
    {
        StartCoroutine(StartLoadScene(sceneName, luaName, LoadSceneMode.Additive));
    }


    public void ChangScene(string sceneName, string luaName)
    {
        Manager.Resource.LoadScene(sceneName, (Object obj) =>
        {
            StartCoroutine(StartLoadScene(sceneName, luaName, LoadSceneMode.Single));
        });
    }

    /// <summary>
    /// 判断场景是否已经加载
    /// </summary>
    /// <param name="sceneName"></param>
    /// <returns></returns>
    private bool IsLoadScene(string sceneName)
    {
        Scene scene = SceneManager.GetSceneByName(sceneName);
        return scene.isLoaded;
    }
    private IEnumerator StartLoadScene(string sceneName, string luaName, LoadSceneMode loadSceneMode)
    {
        if (IsLoadScene(sceneName))
        {
            yield break;
        }
        //
        AsyncOperation async = SceneManager.LoadSceneAsync(sceneName, loadSceneMode);
        //异步加载完成后自动激活场景
        async.allowSceneActivation = true;
        yield return async;

        //在当前已加载的场景中查找名称为 sceneName 的场景。它不会从磁盘或资源文件中加载场景，
        //而是从已经加载到内存中的场景列表中查找。因此，在调用该方法之前，必须确保场景已经被加载到内存中。
        //场景不会通过异步的方式返回回来，因此需要手动查找
        Scene scene = SceneManager.GetSceneByName(sceneName);
        //创建一个挂载场景逻辑的GameObject
        GameObject go = new GameObject(m_LogicName);
        //该GameObject可能因为加载了多个场景，被加载到其他场景，因此需要手动移动
        SceneManager.MoveGameObjectToScene(go, scene);
        //在这一步的时候挂载脚本就会执行awake和start了，但是因为luabehaviour要手动实现awake和start，因此需要
        SceneLogic sceneLogic = go.AddComponent<SceneLogic>();
        sceneLogic.sceneName = sceneName;
        //awake功能的模拟
        sceneLogic.Init(luaName); 
        sceneLogic.OnEnter(); 
    }

    /// <summary>
    /// LoadScene场景的卸载
    /// </summary>
    /// <param name="sceneName"></param>
    private IEnumerator UnLoadSceneAsync(string sceneName)
    {
        //场景卸载的时候需要先调用场景逻辑的OnQuit方法
        Scene scene = SceneManager.GetSceneByName(sceneName);
        if (!scene.isLoaded)
        {
            Debug.LogError("场景未加载");
            yield break;
        }
        SceneLogic sceneLogic = GetSceneLogic(scene);
        sceneLogic?.OnQuit();
        //卸载场景
        AsyncOperation async = SceneManager.UnloadSceneAsync(sceneName);
        yield return async;
    }

    //不知道logic存不存在，也不知道logic在谁身上
    //？？？？为什么，我不是在加载场景的时候就明确挂在m_LogicName对象上了吗
    private SceneLogic GetSceneLogic(Scene scene)
    {
        GameObject[] gameObjects = scene.GetRootGameObjects();
        for (int i = 0; i < gameObjects.Length; i++)
        {
            if (gameObjects[i].name == m_LogicName)
            {
                return gameObjects[i].GetComponent<SceneLogic>();
            }
        }
        return null;
    }
}
